home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac100% 1998 November
/
MAC100-1998-11.ISO.7z
/
MAC100-1998-11.ISO
/
オンラインソフト定点観測
/
ユーティリティ
/
Mops 3.2.sea
/
Mops 3.2
/
Mops source
/
PPC source
/
PPCon68k
< prev
next >
Wrap
Text File
|
1998-06-22
|
9KB
|
380 lines
need struct1
need bytestring
(*
This is a prolog file to load on the 68k Mops, before loading the PPC
code generator. It defines some PPC-specific words in a way that will
allow the code generator to load and run on the 68k, and hopefully
produce proper PPC code.
*)
: TO_BE_WRITTEN 79 die ; ¥ put wherever code isn't written yet
: UWITHIN? ¥ ( u lo hi -- u b ) An unsigned version of WITHIN?
rot tuck u>= down tuck u<= rot and ;
: ALIGN4
DP
4 reserve ¥ just to ensure pad bytes are zero
3 + $ fffffffc and -> DP
;
: ALIGN8
DP
8 reserve
7 + $ fffffff8 and -> DP
;
: #ALIGN2 ( n -- n' ) 1+ -2 and ;
: #ALIGN4 ( n -- n' ) 3 + -4 and ;
: #ALIGN8 7 + $ fffffff8 and ;
: ALIGNED #align4 ; ¥ 4-byte alignment is our default on the PPC
¥ ( ALIGNED is ANSI )
: #ALIGN16 ( n -- n' ) 15 + $ fffffff0 and ;
: #OFF-ALIGN ¥ ( n -- n' ) Aligns to the next 2-byte boundary between
¥ adjacent 4-byte boundaries.
5 + $ fffffffc and 2- ;
: code_allot ++> CDP ;
: code_reserve CDP over erase ++> CDP ;
: code_align CDP 4 erase CDP #align4 -> CDP ;
¥ ================== REGISTER DEFINITIONS ===================
¥ r0 is scratch
1 constant sys_SP_reg
2 constant RTOC_reg
10 constant rZ_reg
11 constant rX_reg
12 constant rY_reg
13 constant mainCode_reg
14 constant mainData_reg
15 constant modCode_reg
16 constant modData_reg
17 constant RP_reg
18 constant SP_reg
19 constant FSP_reg
20 constant obj_base_reg
21 constant I_reg ¥ can be used for a local if no DO...LOOP
¥ or FOR...NEXT
22 constant do_limit_reg ¥ can be used for a local if no DO..LOOP
21 constant 1st_gpr_local
14 constant 1st_fpr_local
¥ Here are some values which are ref'd in a few places in the code
¥ generator but aren't actually needed in the target compilation.
¥ THe real definitions are in pnuc1. Defining them here saves us
¥ putting conditional compilation in a lot of places.
0 value #FP ¥ ref'd in cg3 and cg5
0 value #FPL
0 value CD_gpr#
¥ ==================== ADDRESSING =====================
65520 constant DISPL_RANGE ¥ what we can fit in a signed 16-bits
¥ displacement, rounded down to
¥ 8-byte alignment
32760 constant HALF_DISPL_RANGE
¥ code_start and seg_code_start are now in Nuc.asm so that the 68k (findM) can
¥ use them when in encounters a PPC-style reloc addr.
0 value code_limit
0 value nuc_code_start
0 value data_start
0 value nuc_data_start
0 value data_limit
0 value seg_code_limit
0 value seg_data_start
0 value seg_data_limit
¥ These words give the PPC base reg values while we're target compiling:
: mainCode_val nuc_code_start half_displ_range + ;
: mainData_val nuc_data_start half_displ_range + ;
: modCode_val seg_code_start half_displ_range + ;
: modData_val seg_data_start half_displ_range + ;
0 value comp_seg# ¥ zero unless we're compiling a separate segment
¥ in which case it's the seg# we're compiling
¥ (currently this can only be 10)
: addr>S&D { addr -- seg# displ }
comp_seg#
IF
addr
seg_code_start seg_code_limit
uwithin?
IF ¥ found!
seg_code_start - comp_seg# swap EXIT
THEN
( addr )
seg_data_start seg_data_limit
uwithin?
IF seg_data_start - comp_seg# 1+ swap EXIT
THEN drop
THEN
addr
code_start code_limit
uwithin?
IF code_start - 8 swap EXIT
THEN
( addr )
data_start data_limit
uwithin?
IF data_start - 9 swap EXIT
THEN
0 0 ¥ search failed - return two zeros
;
¥ seg#>gpr# finds if the passed-in seg# corresponds to a base gpr.
¥ If so, it returns the reg#. If not, it returns zero.
: seg#>gpr# ¥ ( seg# -- gpr# )
CASE[ 8 ]=> mainCode_reg EXIT
[ 9 ]=> mainData_reg EXIT
[ 10 ]=> modCode_reg EXIT
[ 11 ]=> modData_reg EXIT
DEFAULT=> drop 0
]CASE
;
¥ B&D takes the passed-in address and converts it to gpr# and displacement.
: (B&D) { theAddr ¥ seg# displ gpr# -- gpr# displ' }
theAddr addr>S&D -> displ -> seg# ¥ both will be zero if theAddr is
¥ not in any segment
seg# seg#>gpr# -> gpr# ¥ will be zero if we didn't get a reg
gpr# mainCode_reg =
IF mainCode_reg
displ code_start + nuc_code_start - half_displ_range -
EXIT
THEN
gpr# mainData_reg =
IF mainData_reg
displ data_start + nuc_data_start - half_displ_range -
EXIT
THEN
gpr#
IF gpr#
displ half_displ_range -
ELSE ¥ theAddr wasn't in range of any reg - return two zeros
0 0
THEN
;
: B&D
(b&d) over
NIF drop cr .h ." is an out-of-range addr!" 1 die THEN
;
¥ @B&D fetches a relocatable addr and returns the "real" base
¥ gpr# and displacement. This is used for going from the code
¥ area to the data area, for values etc.
: @B&D { addr ¥ relocAddr seg# displ gpr# -- gpr# displ' }
addr @ -> relocAddr
relocAddr $ ffffff and -> displ
relocAddr 24 >> -> seg#
seg# seg#>gpr# -> gpr#
gpr# mainCode_reg =
IF mainCode_reg
displ code_start + nuc_code_start - half_displ_range -
EXIT
THEN
gpr# mainData_reg =
IF mainData_reg
displ data_start + nuc_data_start - half_displ_range -
EXIT
THEN
gpr#
IF gpr# displ half_displ_range -
¥ machine instrns use a signed displ, so we
¥ point base regs 32k above the seg start
ELSE ¥ seg# didn't refer to a loaded reg, or was just garbage
70 die ¥ " not a reloc addr"
THEN
;
¥ ===========================================
$ 4E58 constant xinfoMk
0 value tempObj_framesize ¥ we don't target compile temp objects
0 value releaseTemps_xt ¥ since the code generator doesn't use
¥ them, but I can use these value in
¥ testing. The "real" values are
¥ defined in nuc1.
(* CFA_ADJUST fixes a cfa given to us by the 68k compiler to conform
to our PPC alignment convention, if necessary. On the PPC, this
word will do nothing. Once we're compiling PPC code, even on the
68k, FIND et al looks after this for us too. So we only need to
do it if we're looking at the cfa of a PPC-format header while still
not compiling PPC code.
We can always take care of whether the header is in 68k or PPC format
and give the right answer. This is because on the PPC if we need 2 extra
pad bytes for alignment before the handler field, they're always zero,
while a handler field can NEVER be zero. Thus if there's zero where the
handler field would have been on the 68k, and we weren't aligned, this MUST
be a PPC-style header. If we were already aligned, the cfa wouldn't need
changing anyway.
*)
: CFA_ADJUST { cfa ¥ addr al-addr -- cfa' }
PPC? NIF cfa EXIT THEN ¥ not compiling PPC code - leave cfa unchanged
cfa 2- -> addr ¥ back to handler field
addr #align4 -> al-addr ¥ on the PPC this must be 4-byte aligned
addr al-addr <> ¥ did we change it?
IF addr w@ ¥ yes - was that a handler field or padding?
IF cfa EXIT THEN ¥ handler field. It's 68k format. Don't
¥ change original cfa
THEN
al-addr 2+ ¥ padding, or addr didn't change. We return
; ¥ the aligned addr plus 2.
: (PPC_HEADER) { ¥ svDP -- }
PPC?
IF code_align
DP -> svDP
CDP -> DP header
DP -> CDP svDP -> DP
code_align
ELSE
header align4
THEN
;
: (ppc_sHdr) { addr len ¥ svDP -- }
code_align
DP -> svDP
CDP -> DP addr len sHdr
DP -> CDP svDP -> DP
code_align
;
' (ppc_header) -> ppc_header
' (ppc_sHdr) -> ppc_sHdr
: 68kCall db ;
¥ USES_CTR is used like IMMEDIATE, and indicates that the defn just
¥ compiled uses the count register (which will disallow DO loops
¥ calling that defn from using the count reg as the loop counter).
¥ This is normally handled automatically, but for code definitions
¥ this word is useful.
: USES_CTR
$ 40 latest name> #off-align cset ; immediate
false value marker_there?
string+ $tmp
string+ $marker
: BL>01 ¥ ( addr len -- ) Replaces blanks with 01's in the string.
bounds
?DO i c@ bl = IF $ 01 i c! THEN
LOOP
;
: 01>BL ¥ ( addr len -- ) Replaces 01's with blanks in the string.
bounds
?DO i c@ $ 01 = IF bl i c! THEN
LOOP
;
: FNAME>MNAME ¥ ( addr len -- ) Takes the passed-in filename, and converts it to
¥ the corresponding file marker name in $marker.
new: $marker put: $marker
& : <chsearch: $marker negate skip: $marker
<step: $marker delete: $marker
all: $marker bl>01 ¥ replace any blanks
begin: $marker " m__" insert: $marker ¥ prepend "m__"
reset: $marker
;
: MNAME>FNAME ¥ ( addr len -- ) Takes the passed-in marker name, and
¥ converts it to the corresponding filename in $marker.
3 /string ¥ skip the "m__"
new: $marker put: $marker all: $marker 01>bl ¥ and recover any blanks
reset: $marker
;
0 value mk_cfa
:f PPC_mark_file { addr len ¥ rc -- }
" marker" sFind nip 0EXIT ¥ out if MARKER not defined yet
addr len fname>mname
begin: $marker " marker " insert: $marker
lock: $marker all: $marker evaluate
release: $marker
true -> marker_there?
CDP 10 - -> mk_cfa
1 mk_cfa w! ¥ store 1 in word at cfa to show
¥ this is a file mark
getFileInfo: topfile -> rc
topFile 48 + @ code, ¥ put source dirID after marker info
¥ at offs 10 from cfa
topFile 76 + @ code, ¥ then the mod date at offs 14
getName: topfile ¥ this will be the full pathname
dup -> len
CDP place len 1+ ++> CDP ¥ store it after the mod date,
¥ at offs 18
code_align
;f